package dm.service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.sql.Connection;
import java.sql.DriverManager;
import com.mysql.jdbc.Driver;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.dom4j.DocumentException;

import com.mysql.jdbc.exceptions.jdbc4.CommunicationsException;

import algo.LoadBalance;
import dm.bsi.Backup;
import dm.bsi.Container;
import dm.bsi.Deployment;
import dm.bsi.Image;
import dm.bsi.Log;
import dm.bsi.MSDeployment;
import dm.bsi.Node;
import dm.bsi.Service;
import indi.zjh.dp.db.Session;
import indi.zjh.dp.error.CommandExecuteException;
import indi.zjh.dp.error.UnsuportedFieldException;
import indi.zjh.dp.util.FileUtil;
import indi.zjh.dp.util.SystemCmd;


public class MysqlManager implements Manager {

	private static String preLog;
	
	private class PingException extends Exception
	{
		public PingException()
		{
			super();
		}
		
		public PingException(String message)
		{
			super(message);
		}
	}
	
	private class ContainerState
	{
		public static final int STATE_INIT = 0;
		public static final int STATE_CONNECT = 1;
		public static final int STATE_PING = 2;
		
		public static final int MAX_TRY_COUNT = 3;
		
		public int state = STATE_INIT;
		public int tryCount = 0;
		
		private int waitWhenStart = 16;
		
		private Session thisSession = null;
		private String host;
		private int port;
		
		public Session getSession()
		{
			return this.thisSession;
		}
		
		public void connect(String host, int port) throws DocumentException, Exception
		{
			this.host = host;
			this.port = port;
			
			if(this.thisSession != null)
			{
				this.thisSession.close();
			}
			
			// 刚启动需要等待mysql启动完毕
			while(true)
			{
				try
				{
					this.thisSession = new Session(this.host, this.port, "root", "123456", "mysql");
					return;
				}
				catch(CommunicationsException e)
				{
					if(this.waitWhenStart > 0)
					{
						--this.waitWhenStart;
						System.out.println("连接"+host+":"+port+"失败. 等待重连");
						try{ Thread.sleep(2000); }catch(Exception ee){}
					}
					else
					{
						
						StringWriter sw = new StringWriter();
						e.printStackTrace(new PrintWriter(sw));
						throw e;
					}
				}
			}
			
		}
		
		public void ping() throws PingException
		{
			try {
				boolean ret = this.thisSession.getConnection().isValid(10);
				if(!ret)
				{
					throw new PingException("连接失效");
				}
	
				this.tryCount = 0;	
			} catch (SQLException e) {
				// TODO: handle exception
				
				throw new PingException(e.getMessage());
				
			}
			
	
		}
	}

	@Override
		public void process(Session session, Deployment deployment, Service service) throws Exception {
			// TODO Auto-generated method stub
			try{
			MSDeployment msDeployment = (MSDeployment)deployment;
			msDeployment.debug();
			
			long[] containerIds = service.getContainers().getIds();
			Container masterContainer = null;
			ArrayList<Container> slaveContainers = new ArrayList<Container>();
			
			String[] descs = new String[containerIds.length];
			for(int i = 0; i < containerIds.length; ++i)
			{
				Container container = (Container)session.getById(Container.class, containerIds[i]);
				// 忽略状态不明的容器
				if(container.getState() == Container.UNKNOWN)
					continue;
				if(container.refreshDockerPort(session))
				{
					Log.info(session, deployment, "容器"+container.getOid()+"端口发生变化, 更新负载配置");
					Service.agentUpdate(session);
					return;
				}
	//			if(container.isRunning(session))
	//			{
	//				if(container.getRole() == Container.ROLE_MASTER)
	//				{
	//					masterContainer = container;
	//					descs[i] = "master:"+container.getOid();
	//				}
	//				else if(container.getRole() == Container.ROLE_SLAVE)
	//				{
	//					slaveContainers.add(container);
	//					descs[i] = "slave:"+container.getOid();
	//				}
	//			}
	//			else
	//			{
	//				if(container.getRole() == Container.ROLE_MASTER)
	//				{
	//					Log.failure(session, deployment, "master节点"+container.getOid()+"停止运行, "+container.getNode(session).getIp()+":"+container.getDockerPort());
	//				}
	//				else
	//				{
	//					container.destory(session, service);
	//					Log.info(session, deployment, "删除没有运行的slave节点, "+container.getNode(session).getIp()+":"+container.getDockerPort());
	//				}
	//			}
				
				try
				{
					this.ping(session, deployment, container);
					if(container.getRole() == Container.ROLE_MASTER)
					{
						masterContainer = container;
						descs[i] = "master:"+container.getOid();
					}
					else if(container.getRole() == Container.ROLE_SLAVE)
					{
						slaveContainers.add(container);
						descs[i] = "slave:"+container.getOid();
					}
				}
				catch(Exception e)
				{
					container.setState(Container.UNKNOWN);
					if(container.getRole() == Container.ROLE_MASTER)
					{
						StringWriter sw = new StringWriter();
						PrintWriter pw = new PrintWriter(sw); 
						e.printStackTrace(pw);
						
						Log.failure(session, deployment, "master节点"+container.getOid()+"停止运行, "+container.getNode(session).getIp()+":"+container.getDockerPort()+":"+sw.toString());
						container.destory(session, service);
					}
					else 
					{
						container.destory(session, service);
						Log.info(session, deployment, "删除没有运行的slave节点, "+container.getNode(session).getIp()+":"+container.getDockerPort()+":"+e.getMessage());
					}
		
				}
				
			}
			
			String thisLog = "运行容器:"+String.join(",", descs);
			if(preLog == null || !preLog.equals(thisLog))
			{
				Log.info(session, deployment, thisLog);
				preLog = thisLog;
			}
			
	
			// 获取准备就绪的服务器节点
			Node[] nodes = Node.listReadyNodes(session);
			if(nodes.length == 0)
			{
				Log.failure(session, deployment, "当前没有准备就绪的服务器节点, 部署容器被中断");
				return;
			}
			
					
			Image image = deployment.getImage(session);
			
			// 如果没有master, 启动master
			if(masterContainer == null)
			{
				if(slaveContainers.size() == 0)
				{
					Node selectedNode = LoadBalance.getIdlestNode(nodes);
					selectedNode.downloadImage(session, image);
					Container newContainer = new Container();
					HashMap<String, String> env = new HashMap<String, String>();
					env.put("MYSQL_ROOT_PASSWORD", "123456");
					env.put("SERVER_ID", deployment.getCurId()+"");
					deployment.setCurId(deployment.getCurId()+1);
					session.save(deployment).commit();
					newContainer.setRole(Container.ROLE_MASTER);
					newContainer.start(session, deployment, selectedNode, image, false, env);				
					executeMysqlCmd(session, deployment, newContainer, "CREATE USER repl", 10, 5);
					executeMysqlCmd(session, deployment, newContainer, "GRANT REPLICATION SLAVE ON *.* TO repl IDENTIFIED BY 'replpwd'");
	
					String cmd = "scp conf/findPosByTransId.sh root@"+selectedNode.getIp()+":/tmp/";
					String response = SystemCmd.execCMD(cmd, 20);
					Log.info(session, deployment, cmd+":"+response);
					
					cmd = "scp conf/findLatestBinLogFile.sh root@"+selectedNode.getIp()+":/tmp/";
					response = SystemCmd.execCMD(cmd, 20);
					Log.info(session, deployment, cmd+":"+response);
					
					cmd = "ssh root@"+selectedNode.getIp()+" docker cp /tmp/findPosByTransId.sh "+newContainer.getOid()+":/";
					response = SystemCmd.execCMD(cmd, 20);
					Log.info(session, deployment, cmd+":"+response);
					
					cmd = "ssh root@"+selectedNode.getIp()+" docker cp /tmp/findLatestBinLogFile.sh "+newContainer.getOid()+":/";
					response = SystemCmd.execCMD(cmd, 20);
					Log.info(session, deployment, cmd+":"+response);
					
					// master 启动从备份数据恢复数据, 恢复后binlog, 丢失, 所以不支持master从备份文件恢复
//					Backup latestBackup = Backup.getBackup(session, service, null);
//					if(latestBackup != null)
//					{
//						Log.info(session, deployment, "找到备份数据文件:"+latestBackup.getFilepath());
//						//queryMysqlCmd(session, deployment, newContainer, "SHOW MASTER STATUS", 10, 5);
//						HashMap<String, String> posData = latestBackup.restoreData(session, newContainer);
//						latestBackup.getContainer().clear();
//						latestBackup.getContainer().add(newContainer);
//						session.save(latestBackup);
//					}
//				
					
					Service.agentUpdate(session);
					Log.info(session, deployment, "启动master节点"+newContainer.getOid()+", "+selectedNode.getIp()+":"+newContainer.getDockerPort());
					return;
				}
				// 在有slave的情况下master死掉
				else 
				{
					HashMap<Container, Long> slaveToTranId = new HashMap<Container, Long>();
					Iterator<Container> iter = slaveContainers.iterator();
					Container bestSlave = null;
					long maxTransId = 0;
					while(iter.hasNext())
					{
						Container slave = iter.next();
						
						// 等待所有slave的io_thread进程停止
						int tryCount = 0;
						int maxTryCount = 5;
						do {
							List<Map<String, Object>> rows = queryMysqlCmd(session, deployment, slave, "SHOW SLAVE STATUS");
							Map<String, Object> row = rows.get(0);
							if(row.get("Slave_IO_Running").equals("No"))
							{
								break;
							}
							else
							{
								if(tryCount > maxTryCount)
								{
									Log.info(session, deployment, "强制停止slave "+slave.getOid()+" io_thread进程");
									executeMysqlCmd(session, deployment, slave, "STOP SLAVE IO_THREAD");
								}
								++tryCount;
								try {
									Thread.sleep(1000);
								} catch (Exception e) {
									// TODO: handle exception
								}
							}
						} while (true);
						
						// 等待所有的slave执行完所有的同步事件
						tryCount = 0;
						maxTryCount = 10;
						do {
							List<Map<String, Object>> rows = queryMysqlCmd(session, deployment, slave, "SHOW SLAVE STATUS");
							Map<String, Object> row = rows.get(0);
							boolean isSync = false;
							if(row.get("Master_Log_File").equals(row.get("Relay_Master_Log_File")) && row.get("Read_Master_Log_Pos").equals(row.get("Exec_Master_Log_Pos")))
							{
								isSync = true;
							}
							
							if(!isSync && row.get("Slave_SQL_Running").equals("No"))
							{
								isSync = true;
							}
							
							if(isSync)
							{
								// 找到最大的事务Id
								List<Map<String, Object>> vals = queryMysqlCmd(session, deployment, slave, "SHOW DATABASES");
								String dbname = null;
								for(int j = 0; j < vals.size(); ++j)
								{
									String curdb = (String)vals.get(j).get("SCHEMA_NAME");
									if(curdb.equalsIgnoreCase("information_schema") || curdb.equalsIgnoreCase("mysql") || curdb.equalsIgnoreCase("performance_schema") || curdb.equalsIgnoreCase("sys"))
									{
										
									}
									else
									{
										dbname = curdb;
									}
								}
								
								if(dbname != null)
								{
									String sql = "SELECT `_tranid` FROM `"+dbname+"`.`trans` ORDER BY `_tranid` DESC LIMIT 1";
									vals = queryMysqlCmd(session, deployment, slave, sql);
									if(vals.size() > 0)
									{
										long curTransId = ((Long)vals.get(0).get("_tranid")).longValue();
										slaveToTranId.put(slave, new Long(curTransId));
										Log.info(session, deployment, "slave "+slave.getOid()+"获取最大的事务Id:"+curTransId);
										if(curTransId > maxTransId)
										{
											maxTransId = curTransId;
											bestSlave = slave;
										}
									}
								}
								else
								{
									Log.failure(session, deployment, "没有找到业务数据库");
									return;
								}
								
								break;
							}
							else
							{
					
								if(tryCount > maxTryCount)
								{
									Log.info(session, deployment, "强制停止slave "+slave.getOid()+" sql_thread进程");
									executeMysqlCmd(session, deployment, slave, "STOP SLAVE SQL_THREAD");
								}
								++tryCount;
								try {
									Thread.sleep(1000);
								} catch (Exception e) {
									// TODO: handle exception
								}
								
							}
							
							
						} while (true);
						
						// 停止所有的slave同步
						executeMysqlCmd(session, deployment, slave, "STOP SLAVE");
						
					} // end 遍历slave
					
					
					if(bestSlave == null)
					{
						Log.failure(session, deployment, "找不到合适的slave升级为master");
						return;
					}
					
					Log.info(session, deployment, "找到最合适的slave "+bestSlave.getOid()+", 准备升级为master");
					
					// 获取新的slave的最新的binlog日志文件
					Node newMasterNode = bestSlave.getNode(session);
					String cmd = "ssh root@"+newMasterNode.getIp()+" docker exec -i "+bestSlave.getOid()+" ./findLatestBinLogFile.sh";
					String response = SystemCmd.execCMD(cmd, 20);
					Log.info(session, deployment, "获取新master "+bestSlave.getOid()+"的最新的binlog日志文件:"+cmd+":"+response);
					
					String latestBinlogFile = response.trim();
					
					// 再次遍历slave, 指向新的master
					iter = slaveContainers.iterator();
					while(iter.hasNext())
					{
						Container slave = iter.next();
						if(slave == bestSlave)
						{
							continue;
						}
						Node theNode = slave.getNode(session);
						cmd = "ssh root@"+newMasterNode.getIp()+" docker exec -i "+bestSlave.getOid()+" ./findPosByTransId.sh "+latestBinlogFile+" "+slaveToTranId.get(slave).longValue();
						response = SystemCmd.execCMD(cmd, 120).trim();
						if(response.equals("-1"))
						{
							Log.failure(session, deployment, "找不到对应的事务Id");
						}
						String sql = "CHANGE MASTER TO MASTER_HOST='"+newMasterNode.getIp()+"', MASTER_PORT="+bestSlave.getDockerPort()+", MASTER_USER='repl', MASTER_PASSWORD='replpwd',"+response;
						executeMysqlCmd(session, deployment, slave, sql);
						executeMysqlCmd(session, deployment, slave, "START SLAVE");
					}
					
					bestSlave.setRole(Container.ROLE_MASTER);
					session.save(bestSlave).commit();
					return;
				}
			}
			// 检查master的运行状态
			else 
			{
				Node theNode = masterContainer.getNode(session);
				if(!theNode.isReady())
				{
					Log.failure(session, deployment, "Mysql master "+masterContainer.getOid()+" 所处的服务器节点未准备就绪");
					return;
				}
				
				List<Map<String, Object>> rows = queryMysqlCmd(session, deployment, masterContainer, "SHOW MASTER STATUS");
				if(rows.size() == 0)
				{
					Log.failure(session, deployment, "Mysql master服务异常, 严重事故");
					return;
				}
				
				
			}
			
			// 检测slave状态
			for(int i = 0; i < slaveContainers.size(); ++i)
			{
				Container container = slaveContainers.get(i);
				List<Map<String, Object>> rows = queryMysqlCmd(session, deployment, container, "SHOW SLAVE STATUS");
				boolean isNormal = true;
				if(rows.size() == 0)
				{
					Log.failure(session, deployment, "获取slave status错误");
					isNormal = false;
				}
				if(isNormal)
				{
					Map<String, Object> row = rows.get(0);
					if(!row.get("Slave_IO_Running").equals("Yes") || !row.get("Slave_SQL_Running").equals("Yes"))
					{
						Log.failure(session, deployment, "slave "+container.getOid()+" 进程出现异常,"+row);
						isNormal = false;
					}
				}
				
				if(!isNormal)
				{
					container.destory(session, service);
					Log.info(session, deployment, "删除异常的slave "+container.getOid()+" 节点, "+container.getNode(session).getIp()+":"+container.getDockerPort());
					Service.agentUpdate(session);
					return;
				}
			}
			
			// 检测slave, 创建slave以达到期望
			if(slaveContainers.size() < msDeployment.getExpectedSlaveCount())
			{
				List<Map<String, Object>> rows = queryMysqlCmd(session, deployment, masterContainer, "SHOW VARIABLES LIKE 'server_id'");
				if(rows.size() == 0)
				{
					Log.failure(session, deployment, "获取master "+masterContainer.getOid()+" 的server_id失败");
					return;
				}
				
				String server_id = (String)rows.get(0).get("server_id");
				Node masterNode = masterContainer.getNode(session);
				
				Node selectedNode = LoadBalance.getIdlestNode(nodes);
				selectedNode.downloadImage(session, image);
				Container newContainer = new Container();
				HashMap<String, String> env = new HashMap<String, String>();
				env.put("MYSQL_ROOT_PASSWORD", "123456");
				env.put("SERVER_ID", deployment.getCurId()+"");
				deployment.setCurId(deployment.getCurId()+1);
				
				newContainer.setRole(Container.ROLE_SLAVE);
				newContainer.start(session, deployment, selectedNode, image, false, env);
				
				
				// 获取之前的备份
				Backup latestBackup = Backup.getBackup(session, service, masterContainer);
				if(latestBackup == null)
				{
					Log.info(session, deployment, "没有找到备份数据文件, 直接从binlog取数据");
					executeMysqlCmd(session, deployment, newContainer, "CHANGE MASTER TO MASTER_HOST='"+masterNode.getIp()+"', MASTER_PORT="+masterContainer.getDockerPort()+", MASTER_USER='repl', MASTER_PASSWORD='replpwd'", 5, 6);
				}
				else 
				{
					Log.info(session, deployment, "找到备份数据文件:"+latestBackup.getFilepath());
					queryMysqlCmd(session, deployment, newContainer, "SHOW MASTER STATUS", 10, 5);
					HashMap<String, String> posData = latestBackup.restoreData(session, newContainer);
					Log.info(session, deployment, "此时容器的端口:"+newContainer.getDockerPort());
					if(posData == null)
					{
						Log.failure(session, deployment, "通过备份数据文件恢复失败");
						executeMysqlCmd(session, deployment, newContainer, "CHANGE MASTER TO MASTER_HOST='"+masterNode.getIp()+"', MASTER_PORT="+masterContainer.getDockerPort()+", MASTER_USER='repl', MASTER_PASSWORD='replpwd'");
					}
					else 
					{
						Log.info(session, deployment, "posData="+posData);
						String sql = "CHANGE MASTER TO MASTER_HOST='"+masterNode.getIp()+"', MASTER_PORT="+masterContainer.getDockerPort()+", MASTER_USER='repl', MASTER_PASSWORD='replpwd', MASTER_LOG_FILE='"+posData.get("MASTER_LOG_FILE")+"', MASTER_LOG_POS="+posData.get("MASTER_LOG_POS");
						Log.info(session, deployment, "sql="+sql);
						executeMysqlCmd(session, deployment, newContainer, sql, 6, 5);
					}
					
				}
				executeMysqlCmd(session, deployment, newContainer, "START SLAVE");
				
				String cmd = "scp conf/findPosByTransId.sh root@"+selectedNode.getIp()+":/tmp/";
				String response = SystemCmd.execCMD(cmd, 20);
				Log.info(session, deployment, cmd+":"+response);
				
				cmd = "scp conf/findLatestBinLogFile.sh root@"+selectedNode.getIp()+":/tmp/";
				response = SystemCmd.execCMD(cmd, 20);
				Log.info(session, deployment, cmd+":"+response);
				
				cmd = "ssh root@"+selectedNode.getIp()+" docker cp /tmp/findPosByTransId.sh "+newContainer.getOid()+":/";
				response = SystemCmd.execCMD(cmd, 20);
				Log.info(session, deployment, cmd+":"+response);
				
				cmd = "ssh root@"+selectedNode.getIp()+" docker cp /tmp/findLatestBinLogFile.sh "+newContainer.getOid()+":/";
				response = SystemCmd.execCMD(cmd, 20);
				Log.info(session, deployment, cmd+":"+response);
	
				Service.agentUpdate(session);
				Log.info(session, deployment, "启动slave节点, "+selectedNode.getIp()+":"+newContainer.getDockerPort());
	
	
				return;
			}
			
			
			// 删除多余的slave
			if(slaveContainers.size() > msDeployment.getExpectedSlaveCount())
			{
				int stopCount = slaveContainers.size() - msDeployment.getExpectedSlaveCount();
				for(int i = 0; i < slaveContainers.size(); ++i)
				{
					if(i < stopCount)
					{
						slaveContainers.get(i).destory(session, service);
						Log.info(session, deployment, "删除多于预期的slave "+slaveContainers.get(i).getOid()+" 节点, "+slaveContainers.get(i).getNode(session).getIp()+":"+slaveContainers.get(i).getDockerPort());
						Service.agentUpdate(session);
						return;
					}
				}
			}
			
			// 准备备份slave
			if(service.isBackup())
			{
				Backup backup = new Backup();
				int slaveCount = slaveContainers.size();
				if(slaveCount == 0)
				{
					Log.failure(session, deployment, "没有slave节点, 不可备份");
					return;
				}
				int index = 0;
				if(slaveCount > 1)
				{
					Random random = new Random();
					index = random.nextInt(slaveCount-1);
				}
				// 关联当前的master容器
				backup.getContainer().add(masterContainer);
				backup.saveData(session, service, slaveContainers.get(index));
				return;
			}
			// 结束状态机处理
			
			
			}catch(Exception e)
			{
				StringWriter sw = new StringWriter();
				e.printStackTrace(new PrintWriter(sw));
				Log.failure(session, deployment, sw.toString());
				
			}
		}


	private static Hashtable<String, ContainerState> containers = new Hashtable<String, ContainerState>();

	
	
	
	


	
	private List<Map<String, Object>> queryMysqlCmd(Session session, Deployment deployment, Container container, String sql) throws UnsuportedFieldException, DocumentException, Exception
	{
		return queryMysqlCmd(session, deployment, container, sql, 3, 1);
	}
	
	private List<Map<String, Object>> queryMysqlCmd(Session session, Deployment deployment, Container container, String sql, int maxTryCount, int sleepSecond) throws UnsuportedFieldException, DocumentException, Exception
	{
		List<Map<String, Object>> ret = null;
		Node node = container.getNode(session);
		Session mngSession = null;
		int tryCount = 0;
		//int maxTryCount = 16;
		
		while(true)
		{
			try
			{
				ContainerState cs = null;
				if(containers.containsKey(container.getOid()))
				{
					cs = containers.get(container.getOid());
					mngSession = cs.getSession();
					if(mngSession != null)
					{
						ret = mngSession.query(sql);
						return ret;
					}
				}
				
				++tryCount;
				if(tryCount > maxTryCount)
				{
					Log.failure(session, deployment, "连接Mysql失败, 已经重试次数"+tryCount+", 不重试了, 累了, sql="+sql);
					throw new Exception("连接Mysql失败, 已经重试次数"+tryCount+", 不重试了, 累了, sql="+sql);
				}
				else
				{
					if(cs == null || cs.state != ContainerState.STATE_PING)
					{
						
						//tryCount = 0;
						this.ping(session, deployment, container);
						
					}
					Log.info(session, deployment, "连接Mysql失败, 重试次数"+tryCount);
					try
					{
						Thread.sleep(sleepSecond*1000);
					}
					catch(Exception ee)
					{
						
					}
					continue;
				}
				
			}
			catch(Exception e) 
			{
				throw e;
			}

		}
		
	}
	
	private void executeMysqlCmd(Session session, Deployment deployment, Container container, String sql) throws UnsuportedFieldException, DocumentException, Exception
	{
		executeMysqlCmd(session, deployment, container, sql, 3, 1);
	}
	
	private void executeMysqlCmd(Session session, Deployment deployment, Container container, String sql, int maxTryCount, int sleepSecond) throws UnsuportedFieldException, DocumentException, Exception
	{
		
		Node node = container.getNode(session);
		Session mngSession = null;
		int tryCount = 0;
		//int maxTryCount = 16;
		while(true)
		{
			try
			{
				ContainerState cs = null;
				if(containers.containsKey(container.getOid()))
				{
					cs = containers.get(container.getOid());
					mngSession = cs.getSession();
					if(mngSession != null)
					{
						mngSession.execute(sql);
						return;
					}
				}
				
				++tryCount;
				if(tryCount > maxTryCount)
				{
					Log.failure(session, deployment, "连接Mysql失败, 已经重试次数"+tryCount+", 不重试了, 累了, sql="+sql);
					throw new Exception("连接Mysql失败, 已经重试次数"+tryCount+", 不重试了, 累了, sql="+sql);
				}
				else
				{
					if(cs == null || cs.state != ContainerState.STATE_PING)
					{
						//tryCount = 0;
						this.ping(session, deployment, container);
						//continue;
					}
					Log.info(session, deployment, "连接Mysql失败, 重试次数"+tryCount);
					try
					{
						Thread.sleep(sleepSecond*1000);
					}
					catch(Exception ee)
					{
						
					}
					continue;
				}
				



			}
			catch(Exception e) 
			{
				throw e;
			}
			
		}
		

	}

	@Override
	public void ping(Session session, Deployment deployment, Container container) throws Exception {
		// TODO Auto-generated method stub
		// 容器未被添加进管理池
		if(!containers.containsKey(container.getOid()))
		{
			ContainerState cState = new ContainerState();
			containers.put(container.getOid(), cState);
		}

		ContainerState thisState = containers.get(container.getOid());
		Node node = container.getNode(session);
		
		try
		{
			switch (thisState.state) {
			case ContainerState.STATE_INIT:
				thisState.state = ContainerState.STATE_CONNECT;
				break;
					
			case ContainerState.STATE_CONNECT:
				thisState.connect(node.getIp(), container.getDockerPort());
				thisState.state = ContainerState.STATE_PING;
				break;
				
			case ContainerState.STATE_PING:
				thisState.ping();
				thisState.state = ContainerState.STATE_PING;
				break;
						
			default:
						
				break;
			}
		}
		catch(PingException ee)
		{
			thisState.state = ContainerState.STATE_INIT;
			Log.failure(session, deployment, "容器"+container.getOid()+"连接异常,"+ee.getMessage());
			if(thisState.tryCount++ >= ContainerState.MAX_TRY_COUNT)
			{
				containers.remove(container.getOid());
				container.setState(Container.UNKNOWN);
				session.save(container).commit();
				throw new Exception(ee.getMessage());
			}
		}
		catch (CommunicationsException e) {
			// TODO: handle exception
			container.setState(Container.UNKNOWN);
			session.save(container).commit();
		}
	}

}
